<?php

namespace IDock\Insurance\QHIC\Request;

use Exception;
use IDock\Insurance\QHIC\QHICEnums;
use IDock\Insurance\QHIC\Request\AllQHICRequest;
use IDock\Insurance\QHIC\Response\PremiumInquiryResponse;
use IDock\Printer\NonCar\NonCarSubCoveragePrinter;
use IDock\Visitor\NonCar\NonCarProductVisitor;
use IDock\Visitor\Premium\PremiumChargingPileVisitor;
use IDock\Visitor\Premium\PremiumCoverageVisitor;
use IDock\Visitor\Premium\PremiumInquiryVisitor;
use IDock\Visitor\Premium\PremiumRelationVisitor;

class PremiumInquiryRequest extends AllQHICRequest
{
    public $requestType = 'VHL0005';

    protected $response = PremiumInquiryResponse::class;

    protected $urlTip = '报价接口';

    /*** @var  PremiumInquiryVisitor $visitor */
    protected $visitor;

    public function generate(): array
    {
        $this->flowId = $this->visitor->getVehicleVisitor()->argc['flowId'] ?? '';
        $data = [
            'Base' => $this->mainData(),
            'Vhl' => $this->carData(),
            'Vhlowner' => $this->getOwnerData(),
            'CvrgList' => $this->getCoverageList(),
            'VsTax' => $this->carShipTax(),
            'ChargerList' => $this->chargingList(),
            'PrmCoef' => [
                'CCommissionFlag' => '0',//费折联动标志
                'NExpDisc' => $this->visitor->getExtInfoVisitor()->expectedDiscount,//期望定价系数
            ],
            'NovehicleList' => $this->getNoCarList(),
        ];

        return $data;
    }

    private function getOwnerData()
    {
        $owner = $this->visitor->getOwnerVisitor();
        $ownerData = [
            'COwnerNme' => $owner->name,
            'COwnerCls' => $owner->typeCode == 'R1' ? '1' : '3',
            'CCertfCls' => QHICEnums::$certificateTypeCode[$owner->certificateTypeCode] ?? '',
            'CCertfCde' => $owner->certificateNo,
        ];
        if($this->visitor->getOwnerVisitor()->typeCode == 'R1'){
            $ownerData['CSex'] = $this->getGenderByIDcard($this->visitor->getOwnerVisitor()->certificateNo);
            $ownerData['TBirthday'] = $this->getBirthday($this->visitor->getOwnerVisitor()->certificateNo);
        }
        if(empty($ownerData)){
            throw new Exception("不支持该车主证件类型");
        }
        return $ownerData;

    }

    /**
     * 主信息
     * @return array
     */
    private function mainData(): array
    {
        $data = [
            'CAppNo' => $this->visitor->getExtInfoVisitor()->argc['CAppNo'] ?? '',//申请单号（交强）
            'SY_CAppNo' => $this->visitor->getExtInfoVisitor()->argc['SY_CAppNo'] ?? '',//申请单号(商业)
            'TInsrncBgnTm' => $this->visitor->ciStartData ? date('YmdHis',strtotime($this->visitor->ciStartData)) : '',//保险起期（交强）
            'TInsrncEndTm' => $this->visitor->ciEndData ? date('YmdHis',strtotime($this->visitor->ciEndData)) : '',//保险止期（交强）
            'SY_TInsrncBgnTm' => $this->visitor->biStartData ? date('YmdHis',strtotime($this->visitor->biStartData)) : '',//保险起期（商业）
            'SY_TInsrncEndTm' => $this->visitor->biEndData ? date('YmdHis',strtotime($this->visitor->biEndData)) : '',//保险止期（商业）
            'CRenewMrk' => $this->visitor->getVehicleVisitor()->isNewVehicle ? "0" : "1",//续保标志
            'CImmeffMrk' => strval(intval($this->visitor->ciEffectFlag)),//即时生效（交强）
            'SY_CImmeffMrk' => strval(intval($this->visitor->biEffectFlag)),//即时生效（商业）
            'CAgentNo' => $this->visitor->getExtInfoVisitor()->argc['CAgentNo'] ?? '',//代理员id
            'CBrkrCde' =>$this->visitor->getExtInfoVisitor()->argc['CBrkrCde'] ?? '',//代理人编码
            //'CBrkrCde' => $this->CBrkrCde,//代理人编码
        ];
        //险种联合类型
        if ($this->visitor->ciStartData) {
            $data['CProdNo'] = '030001';
        }
        if ($this->visitor->biStartData) {
            $data['CProdNo'] = '033015';
            if($this->visitor->getVehicleVisitor()->isNewEnergy){
                $data['CProdNo'] = '033019';
            }
        }
        if ($this->visitor->biStartData && $this->visitor->ciStartData) {
            $data['CProdNo'] = '033015_030001';
            if($this->visitor->getVehicleVisitor()->isNewEnergy){
                $data['CProdNo'] = '033019_030001';
            }
        }
        return $data;
    }

    /**
     * 车辆信息
     * @return array
     */
    private function carData(): array
    {
        $data = [
            'CEngNo' => $this->visitor->getVehicleVisitor()->engineNo,
            'CFrmNo' => $this->visitor->getVehicleVisitor()->vin,//车主类型
            'CFstRegYm' => date('Ymd',strtotime($this->visitor->getVehicleVisitor()->firstRegisterDate)),//小型汽车
            'CResvTxt8' => date('Ymd',strtotime($this->visitor->getVehicleVisitor()->issueDate)) ,//行驶证发证日期
            'CModelCde' => $this->visitor->getVehicleVisitor()->vehicleModelCode,//车型编码
            'CDevice1Mrk' => ($this->visitor->getVehicleVisitor()->isTransfer or $this->visitor->getVehicleVisitor()->isCiTransfer) ? '1' : '0',
            'NNagoActualValue' => $this->visitor->getVehicleVisitor()->actualValue,//协商价格
            'CUsageCde' => QHICEnums::$causeType[$this->visitor->getVehicleVisitor()->causeType] ?? '',//使用性质
            'CVhlTyp' => $this->getCVhlTyp(),//车辆种类
            'CRegVhlTyp' => $this->visitor->getVehicleVisitor()->vehicleStyleCode,//交管车辆种类
            'CRiskDesc' => 'T001',//车型标志 默认正常车型
            'CPlateNo' => $this->visitor->getVehicleVisitor()->licenseNo,
            'CPlateTyp' => QHICEnums::$licenseTypeCode[$this->visitor->getVehicleVisitor()->licenseTypeCode] ?? '',//号牌种类
            'CTravelAreaCde' => '0',//行驶区域 全国
            'CSaleCoName' => '',
            'CSaleProvince' => '',
            'CSaleCity' => '',
            'CFuelType' => QHICEnums::$energyType[$this->visitor->getVehicleVisitor()->energyTypeCode] ?? '',//车辆能源类型
            'CInspectorNme' => QHICEnums::$carCheckCode[$this->visitor->getExtInfoVisitor()->carCheckCode] ?? '',//验车状态
            'CInspectionCde' => QHICEnums::$carCheckReasonKind[$this->visitor->getExtInfoVisitor()->carCheckReasonKind] ?? '',//免验车原因
            'NSeatNum' => $this->visitor->getVehicleVisitor()->vehicleSeat,
            'NTonage' => $this->visitor->getVehicleVisitor()->vehicleTonnage,
            'NCurbWt' => $this->visitor->getVehicleVisitor()->wholeWeight,
            'NDisplacement' => $this->visitor->getVehicleVisitor()->vehicleExhaust,
        ];
        if(strpos($data['NCurbWt'],';') !== false){
            $data['NCurbWt'] = explode(';',$data['NCurbWt']);
            $data['NCurbWt'] = $data['NCurbWt'][0];
        }
        if($data['CDevice1Mrk']){
            $data['TTransferDate'] = date('Ymd',strtotime($this->visitor->getVehicleVisitor()->transferDate));
        }
        if($this->visitor->getVehicleVisitor()->isNewEnergy){
            $data['CVhlSubTyp'] = '';
        }
        if(empty($data['CInspectionCde']) && $this->visitor->getExtInfoVisitor()->carCheckCode == 'CS2'){
            throw new \Exception("不支持该免验车原因");
        }
        if(empty($data['CPlateTyp'])){
            throw new \Exception("不支持该号牌种类");
        }
        return $data;
    }

    private function getCVhlTyp()
    {
        $code = '';
        $seat = $this->visitor->getVehicleVisitor()->vehicleSeat;
        $carKind = $this->visitor->getVehicleVisitor()->carKindCode;
        $weight = round(intval($this->visitor->getVehicleVisitor()->vehicleTonnage) / 1000,2);
        if($carKind == '100'){
            //客车
            if($seat < '6'){
                $code = '365001';
            }elseif($seat < '10'){
                $code = '365002';
            }elseif($seat < '20'){
                $code = '365003';
            }elseif($seat < '36'){
                $code = '365004';
            }else{
                $code = '365005';
            }
        }elseif ($carKind == '200'){
            //货车
            if($weight < '2'){
                $code = '365006';
            }elseif ($weight < '5'){
                $code = '365007';
            }elseif ($weight < '10'){
                $code = '365008';
            }else{
                $code = '365009';
            }
        }
        if(empty($code)){
            throw new \Exception("不支持的车辆种类");
        }
        return $code;
    }

    /**
     * 险种信息
     * @return array
     */
    private function getCoverageList(): array
    {
        $list = [];

        $coverageList = $this->visitor->getCoverageVisitorList();
        foreach ($coverageList as $coverage) {

            /*** @var PremiumCoverageVisitor $coverage */
            if (!in_array($coverage->coverageCode,['C16001','C16002','C16003'])) {
                $coverage->coverageCode = str_replace('C1','C0',$coverage->coverageCode);
            }
            $one = [
                'CCvrgNo' => QHICEnums::$coverageCode[$coverage->coverageCode] ?? '',
                'NAmt' => $coverage->amount,
            ];

            //服务次数
            if (in_array($one['CCvrgNo'], ['033027', '033028', '033029'])) {
                $one['NServiceTimes'] = $coverage->serviceTimes;
            }
            //绝对免赔率
            if (in_array($one['CCvrgNo'], ['033031', '033032', '033033','033034','033035'])) {
                $one['NDeductibleRate'] = $coverage->deductionRate ? round($coverage->deductionRate / 100,2) : '';
            }
            //座位数/天数
            if (in_array($one['CCvrgNo'], [ '033003', '033004', '033009', '033038','033040'])) {
                $one['NLiabDaysLmt'] = $coverage->quantity;
                $one['NPerAmt'] = $coverage->unitAmount ?: $coverage->amount;
                if($one['CCvrgNo'] == '033003'){
                    $one['NLiabDaysLmt'] = 1;
                }
                if($one['CCvrgNo'] == '033004' || $one['CCvrgNo'] == '033038' || $one['CCvrgNo'] == '033040'){
                    $one['NLiabDaysLmt'] = $this->visitor->getVehicleVisitor()->vehicleSeat - 1;
                }
            }
            if($one['CCvrgNo'] == '033001'){
                //车损险
                $one['NAmt'] = $this->visitor->getVehicleVisitor()->actualValue;
            }

            $list[] = $one;
        }
        return $list;
    }

    /**
     * 其他车险
     * @return array
     */
    private function getNoCarList():array
    {
        $list = [];
        if (!$this->visitor->getNonCarInquiryVisitor()->getNonCarList()) {
            return $list;
        }
        /*** @var NonCarProductVisitor $NonCarProductVisitor */
        foreach ($this->visitor->getNonCarInquiryVisitor()->getNonCarList() as $NonCarProductVisitor) {
            $list[] =[
                'CRuleNo' => $NonCarProductVisitor->planCode,
                'TInsrncBgnTm' => $this->visitor->biStartData,
                'TInsrncEndTm' => $this->visitor->biEndData,
                'NCopiesNum' => $NonCarProductVisitor->insuredNum,
                'CNovehicleAppNo' => '',
                'NTgtQty' => '',
                'CProdNo' => $NonCarProductVisitor->productCode,
            ];
        }

        return $list;
    }

    /**
     * 充电桩
     * @return array
     */
    private function chargingList(): array
    {
        $list = [];
        $no = 1;
        foreach ($this->visitor->getChargingPileVisitorList() as $visitor) {
            /*** @var PremiumChargingPileVisitor $visitor */
            $kindList = [
                'NSeqNo' => (string)$no,
                'CChargerType' => $visitor->chargingPileType,//充电桩型号
                'CChargerCode' => $visitor->chargingPileCode,//充电桩编码
                'CChargerAddress' => $visitor->chargingPileAddress,//充电桩地址
                'CChargerAddressType' => QHICEnums::$chargingPileAddressType[$visitor->chargingPileAddressType],
                'CChargerKind' => QHICEnums::$chargingPileKind[$visitor->chargingPileKind],
                'CChargerYearLimit' => QHICEnums::$chargingPileYearLimit[$visitor->chargingPileYearLimit],
                'NLossAmt' => $visitor->lossAmount,
                'TLossBgnTm' => date('YmdHis',strtotime($this->visitor->biStartData)),
                'TLossEndTm' => date('YmdHis',strtotime($this->visitor->biEndData)),
                'CLossIndemLmtLvl' => $visitor->lossAmount,
                'NLiabAmt' => $visitor->liabilityAmount,
                'NLiabIndemLmt' => $visitor->liabilityAmount,
                'TLiabBgnTm' => date('YmdHis',strtotime($this->visitor->biStartData)),
                'TLiabEndTm' => date('YmdHis',strtotime($this->visitor->biEndData)),
                'CLiabIndemLmtLvl' => round(intval($visitor->liabilityAmount) / 10000),
                'CLiabCancelFlag' => '',
                'CLossCancelFlag' => '',
            ];
            $list[] = $kindList;
            $no += 1;
        }
        return $list;

    }

    /**
     * 车船税
     * @return array
     */
    private function carShipTax(): array
    {
        $taxVisitor = $this->visitor->getCarTaxVisitor();

        $arr = [
            'CPaytaxTyp' => QHICEnums::$taxTypeCode[$taxVisitor->taxTypeCode] ?? '',//纳税方式
            'TTaxEffBgnTm' => date('Ymd',strtotime($taxVisitor->taxStartDate)),//缴费起始年月
            'TTaxEffEndTm' => date('Ymd',strtotime($taxVisitor->taxEndDate)),//缴费终止年月
        ];
        if(empty($arr['CPaytaxTyp'])){
            throw new \Exception("不支持该纳税类型");
        }
        //完税
        if($arr['CPaytaxTyp'] == '3T5005'){
            $arr['CTaxPaymentRecptNo'] = $taxVisitor->taxpayerCertificateNo;
            $arr['CComTaxOrg'] = $taxVisitor->taxDepartment;
            $arr['TCertificateDate'] = date('Ymd',strtotime($taxVisitor->taxDocumentDate)) ;
            $arr['CTaxPaidAreaCode'] = $taxVisitor->taxPaidAreaCode;
        }
        //减免税
        if($arr['CPaytaxTyp'] == '3T5004' || $arr['CPaytaxTyp'] == '3T5003'){
            $arr['CTaxfreeVhltyp'] = QHICEnums::$taxReductionReasonCode[$taxVisitor->taxReductionReasonCode] ?? '';
            $arr['CTaxReliefCertNo'] = $taxVisitor->taxDocumentNumber;//减免税凭证号
            $arr['CFreeTaxOrg'] = $taxVisitor->taxDepartment;//减免税税务机关名称
            $arr['CAbateRsn'] = $taxVisitor->taxReductionCode;//减免税方案
            if($arr['CAbateRsn'] == 'P'){
                $arr['CAbateProp'] = $taxVisitor->taxFreeRate;//减免比例
            }elseif ($arr['CAbateRsn'] == 'A'){
                $arr['CAbateAmt'] = $taxVisitor->taxExemption;//减税金额
            }


        }
        return $arr;
    }

    /**
     * 生日
     * @param $idCard
     * @return string
     */
    private function getBirthday($idCard)
    {
        if (strlen($idCard) != 18) {
            throw new Exception("身份证位数不合法");
        }
        return substr($idCard, 6, 8);
    }

    /**
     * 通过身份证获取性别
     * @param $idcard
     * @return int
     * @throws \Exception
     */
    private function getGenderByIDcard($idCard)
    {
        if (strlen($idCard) != 18) {
            throw new \Exception("身份证位数不合法");
        }
        $gender = intval(substr($idCard, 16, 1)) % 2;
        return $gender ? '1' : '2';
    }
}
